package it.gius.applets;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.jbox2d.common.Vec2;

import it.gius.pe.aabb.AABBSweepAndPrune;
import it.gius.pe.aabb.AABoundaryBox;
import it.gius.pe.aabb.Pair;
import it.gius.pe.data.ShapesListNode;
import it.gius.pe.data.structures.IdArrayListA;
import it.gius.processing.util.MyAbstractPApplet;



@SuppressWarnings("serial")
public class AABBsApplet extends MyAbstractPApplet{
	
	private IdArrayListA<ShapesListNode> list;
	private Pair[] pairs;
	private int pairsNumber;
	private AABBSweepAndPrune sap;
	
	private Map<Short,Boolean> overlapping;
	
	private boolean move = true;
	
	private Random random;
	
	
	public AABBsApplet(IdArrayListA<ShapesListNode> list) {
		this.list = list;
		overlapping = new HashMap<Short, Boolean>();
		sap = new AABBSweepAndPrune();
		
		int index = list.rootNode;
		for(int i=0; i< list.getNodeNumber(); i++)
		{
			ShapesListNode node =  list.a_list[index];
			
			overlapping.put(node.id, false);
			
			index = node.next;
		}
		
		random = new Random(System.currentTimeMillis());
		
	}
	
	
	
	public void setup(){
		
		size(400,400);
		
		sap.init(list);
		
		pairs = sap.updateAndGetPairs();
		pairsNumber = sap.getPairsNumber();
		
		
		if(!goStop.isGo())
			noLoop();
	}
	

	@Override
	public void keyPressed() {
		super.keyPressed();
		
		move = true;
		
		if(key == 'm' && !goStop.isGo())
			redraw();
		
		if( key== 'c' && !goStop.isGo())
		{
			move = false;
			redraw();
		}
		
		if( key == 'a' ) //add
		{
			move = false;
			ShapesListNode node = new ShapesListNode();
			node.box = new AABoundaryBox();
			
			AABoundaryBox box = node.box;

			 box.lowerBound.x =  5+ 350*random.nextFloat();
			 box.upperBound.x = box.lowerBound.x +5+ 40*random.nextFloat();
			 
			 box.lowerBound.y =  5+ 350*random.nextFloat();
			 box.upperBound.y = box.lowerBound.y +5+ 40*random.nextFloat();
			
			list.addItem(node);
			
			sap.addAABB(node.box, node.id);
			
			redraw();
		}
		
		
		if( key == 'r' ) //remove
		{
			move = false;
						
			int n = random.nextInt(list.getNodeNumber()-1);
			ShapesListNode node;
			
			int index = list.rootNode;
			
			for(int i=0; i<n; i++)
			{
				node = list.a_list[index];
				index = node.next;
			}
			
			node = list.a_list[index];
			
			sap.removeAABB(node.box);
			
			
			list.removeItem(node.id);
			
			redraw();
		}
		
	}
	
	
	public void draw()
	{
		//println("draw");
		
		if(move)
			move();
		
		//sap.sortAndSweepAll();
		int index = list.rootNode;
		ShapesListNode node;
		AABoundaryBox box;
		for(int i=0; i< list.getNodeNumber(); i++)
		{
			node = list.a_list[index];
			box = node.box;
			
			sap.updateAABB(box);
			
			index = node.next;
		}
		
		pairs = sap.updateAndGetPairs();
		pairsNumber = sap.getPairsNumber();
		
		System.out.print("[ ");
		for(int i=0; i< pairsNumber; i++)
			System.out.print(pairs[i] +", ");
		
		System.out.println(" ]");
		
		background(255);
	
		System.out.println("Draw");
		
		noFill();
		strokeWeight(1);
		
		index = list.rootNode;
		for(int i=0; i< list.getNodeNumber(); i++)
		{
			node =  list.a_list[index];
			
			overlapping.put(node.id, false);
			
			index = node.next;
		}
		
		for(int i=0; i<pairsNumber; i++)
		{
			overlapping.put(pairs[i].idShapeA, true);
			overlapping.put(pairs[i].idShapeB, true);
		}
				
		
		index = list.rootNode;

		
		for(int i=0; i< list.getNodeNumber();i++)
		{
			node = list.a_list[index];
			box = node.box;
			
			//drawBBox(bboxs[i]);
			Vec2 l = box.lowerBound;
			Vec2 u = box.upperBound;

			
			
			stroke(0);
			fill(0);
			
			int averageX = (int)(u.x+l.x)/2;
			int averageY = (int)(u.y+l.y)/2;
			text(node.id,averageX, averageY);
			noFill();
			strokeWeight(1);
			if(overlapping.get((short)index))
				stroke(240,0,0);
			else
				stroke(0,0,240);
			
			rect(l.x,l.y, u.x - l.x, u.y - l.y);
			
			
			index = node.next; 
		}
		

		
		
	}
	
	
	private void move()
	{
		 
		 Random random = new Random(System.currentTimeMillis());
		 
		 int index = list.rootNode;
		 for(int i=0; i<list.getNodeNumber(); i++)
		 {
			 ShapesListNode node = list.a_list[index];
			 AABoundaryBox box = node.box;
			 
			 box.lowerBound.x = (box.lowerBound.x -5) +10*random.nextFloat();
			 box.upperBound.x = box.lowerBound.x +5 +40*random.nextFloat();
			 
			 box.lowerBound.y = (box.lowerBound.y -5) +10*random.nextFloat();
			 box.upperBound.y = box.lowerBound.y +5 +40*random.nextFloat();
			 
			 index = node.next;
		 }
	}
	
	
	/*private void drawBBox(BoundaryBox bbox)
	{
		Vec2 l = bbox.getLowerBound();
		Vec2 u = bbox.getUpperBound();
		
		beginShape();
		vertex(l.x,l.y);
		vertex(l.x,u.y);
		vertex(u.x,u.y);
		vertex(u.x,l.y);
		endShape(PApplet.CLOSE);
	}*/

}
